package tools;

import data.vectors.*;
import data.vectors.implementation.*;


public class Maths {

	public static double getLogSumUsingLog(double[] values)
	{
		double[] temp=values.clone();
		//Find the lowest value
		double min=Double.POSITIVE_INFINITY;
		for(int i=0;i<values.length;i++)
		{
			temp[i]=values[i];
			if (values[i]<min) min=values[i];
		}
		
		if(min==Double.NEGATIVE_INFINITY)
		{
			min=-5000;
		}
		
		//Scalling
		double somme=0.0;
		for(int i=0;i<values.length;i++)
			somme+=Math.exp(temp[i]-min);
		
		return(Math.log(somme)+min);
	}
	
	public static double dotproduct(double[] x,double y[])
	{
		double retour=0.0;
		for(int i=0;i<x.length;i++)
			retour+=x[i]*y[i];
		return(retour);
	}
	
	/**
	 * Calcul du vecteur de conjonction entre v1 et v2
	 * @param v1
	 * @param v2
	 * @return
	 */
	public static DoubleVector conjonction(DoubleVector v1,DoubleVector v2)
	{
		if (v2.size()==0) return(v1);
		//Log.sendMessage("info", this.getClass().getName(),v1.size()+" et "+v2.size()+" -> "+v1.size()*v2.size());
		DoubleVector_Sparse_Memory v=new DoubleVector_Sparse_Memory(v1.size()*v2.size());
		DoubleVectorIterator iterator=v2.getNonNullIterator();
		while(iterator.hasNext())
		{
			iterator.next();
			int feature=iterator.getCurrentFeature();
			double value=iterator.getCurrentValue();
			//Log.sendMessage("info", this.getClass().getName(),"\tDasn v2 = "+feature+":"+value);
			DoubleVectorIterator iterator2=v1.getNonNullIterator();
			while(iterator2.hasNext())
			{
				iterator2.next();
			//	Log.sendMessage("info", this.getClass().getName(),"\t\tDans v1 ="+iterator2.getCurrentFeature()+":"+iterator2.getCurrentValue());
				int nf=v1.size()*feature+iterator2.getCurrentFeature();
			//	Log.sendMessage("info", this.getClass().getName()," Donne : "+nf);
				v.setValue(nf,iterator2.getCurrentValue()*value);
			}						
		}
		
		return(v);
	}
	
	//Effectue un tirage aleatoire par rapport � un ensemble de proba (non normalis�es)
	public static int tirageAleatoire(double[] nproba)
	{		
		double tirage=Math.random();
		int pos=0;
		double v=nproba[0];
		while(tirage>v)
		{
			pos++;
			v+=nproba[pos];
		}
		return(pos);
	}
	
	public static double[] normalize(double[] proba)
	{
		double somme=0.0;
		double[] nproba=new double[proba.length];
		for(int t=0;t<proba.length;t++) somme+=proba[t];
		for(int t=0;t<proba.length;t++) nproba[t]=proba[t]/somme;
		return(nproba);
	}
	
	public static double[] lognormalize(double[] logproba)
	{
		double[] nproba=new double[logproba.length];
		double somme=Maths.getLogSumUsingLog(logproba);
		for(int t=0;t<logproba.length;t++) nproba[t]=logproba[t]-somme;
		return(nproba);
	}
	
	public static double[] exponentiel(double[] proba,double T)
	{
		double nproba[]=new double[proba.length];
		for(int i=0;i<proba.length;i++)
		{
			nproba[i]=Math.pow(proba[i],T);
		}
		nproba=Maths.normalize(nproba);
		return(nproba);
	}

	//Effectue un tirage aleatoire par rapport � un ensemble de proba (non normalis�es)
	public static int tirageMax(double[] proba)
	{
		double maxv=Double.NEGATIVE_INFINITY;
		int maxpos=-1;
		for(int t=0;t<proba.length;t++)
			if (proba[t]>maxv) {maxv=proba[t]; maxpos=t;}
		
		return(maxpos);
	}
	
	
}
